#include "include.h"
#include "func.h"
#include "func_clock.h"

#if FUNC_CLOCK_EN
rtc_time_t rtc_tm AT(.buf.rtc.clock);
time_cb_t tm_cb AT(.buf.rtc.clock);

AT(.text.func.clock.tbl)
const char week_str[7][4] = {
    "Sun",
    "Mon",
    "Tue",
    "Wed",
    "Thu",
    "Fri",
    "Sat",
};

AT(.text.func.clock.init)
void rtc_clock_init(void)
{
    rtc_tm.tm_year = (2019-1970);
    rtc_tm.tm_mon  = 7;
    rtc_tm.tm_mday = 11;
    rtc_tm.tm_hour = 23;
    rtc_tm.tm_min  = 59;
    rtc_tm.tm_sec  = 0;
    rtc_tm.tm_wday = get_weekday(rtc_tm.tm_year, rtc_tm.tm_mon, rtc_tm.tm_mday);
    RTCCNT = rtc_tm_to_time(&rtc_tm);
}

//多少秒后闹钟响
AT(.text.func.clock)
void rtc_set_alarm_relative_time(u32 nsec)
{
    rtc_time_to_tm(RTCCNT, &rtc_tm);            //更新时间结构体
    RTCALM = rtc_tm_to_time(&rtc_tm) + nsec;    //设置闹钟相对于当前时间n秒后
}

//设置多少秒后闹钟唤醒
AT(.text.func.clock)
void rtc_set_alarm_wakeup(u32 nsec)
{
    uint rtccon3 = RTCCON3;

    RTCCPND = BIT(17);                          //clear RTC alarm pending
    RTCCON9 = BIT(0);                           //clear alarm pending
    rtc_set_alarm_relative_time(nsec);

    rtccon3 |= BIT(8);                          //RTC alarm wakeup enable
    RTCCON3 = rtccon3;
}

AT(.text.func.clock)
void func_clock_process(void)
{
    func_process();

#if !GUI_LCD_EN
    //通过ALARM每隔5秒打印一次时间，仅用于测试
    if (RTCCON & BIT(17)) {
        RTCCPND = BIT(17);                      //clear RTC alarm pending
        RTCCON9 = BIT(0);                       //clear alarm pending
        if (!tm_cb.setting) {
            rtc_time_to_tm(RTCCNT, &rtc_tm);           //更新时间结构体
            RTCALM = rtc_tm_to_time(&rtc_tm) + 4;                          //设置闹钟相对于当前时间5秒后
            printf("time:  %d.%02d.%02d   %02d:%02d:%02d  %s\n", (rtc_tm.tm_year+1970), rtc_tm.tm_mon, rtc_tm.tm_mday,
                       rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec, week_str[rtc_tm.tm_wday]);
        }
    }
#endif
}

static void func_clock_enter(void)
{
    func_process();
    memset(&tm_cb, 0, sizeof(tm_cb));

    func_cb.mp3_res_play = mp3_res_play;
    sys_cb.rtc_first_pwron = 0;
    rtc_time_to_tm(RTCCNT, &rtc_tm);         //更新时间结构体
    RTCALM = rtc_tm_to_time(&rtc_tm)+4;      //设置闹钟相对于当前时间5秒后
    func_clock_enter_display();
#if WARNING_FUNC_CLOCK
    mp3_res_play(RES_BUF_CLOCK_MODE_MP3, RES_LEN_CLOCK_MODE_MP3);
#endif // WARNING_FUNC_CLOCK
}

static void func_clock_exit(void)
{
    func_clock_exit_display();
    func_cb.last = FUNC_CLOCK;
}

AT(.text.func.clock)
void func_clock(void)
{
    printf("%s\n", __func__);

    func_clock_enter();

    while (func_cb.sta == FUNC_CLOCK) {
        func_clock_process();
        func_clock_message(msg_dequeue());
        func_clock_display();
    }

    func_clock_exit();
}

#if ALARM_WAKEUP
#define FMRXANGCON0     SFR_RW (SFR5_BASE + 0x18*4)
#define MDMSFR_BASE   0x00007c00
#define RFPWRCON0      SFR_RW (MDMSFR_BASE + 0x48*4)  //RFPOWER_CNTL
#define RFTXRSV        SFR_RW (MDMSFR_BASE + 0x38*4)  //PLL_RC_CALIB_STAT
#define RFSXRSV        SFR_RW (MDMSFR_BASE + 0x39*4)  //FILTER_RC_CALIB_STAT
#define RFRXRSV        SFR_RW (MDMSFR_BASE + 0x3c*4)  //VCOFC_ICP_CALIBSTAT
#define RFPLLCON0      SFR_RW (MDMSFR_BASE + 0x1c*4)  //RPLLCNTL0
#define FMRXANGCON2     SFR_RW (SFR5_BASE + 0x1a*4)
//调用函数rtc_set_alarm_wakeup（nsec）。nsec（秒）之后闹钟唤醒。////
AT(.com_text.bsp.key)
void rtc_power_test(void)
{
    u32 i,p111_en;
    u32 io_ade, io_bde, io_ede, io_fde,io_gde,gie;
    u32 io_fpu,io_fpd, io_fpd200k, io_fpu200k,io_fpd300, io_fpu300;
    u32 clkcon0,pwrcon0,pll0con,usbcon0,xo26mcon,fmrxangcon0,fmrxangcon2,lpmcon;
    u32 rfpwrcon0, rftxrsv, rfsxrsv, rfrxrsv, rfpllcon0;
    u32 rtccon3, rtccon4, rtccon5;
    u16 adc_ch;
    bt_enter_sleep();
    dac_power_off();                    //dac power down
    saradc_exit(adc_cb.channel);        //close saradc及相关通路模拟
    sys_set_tmr_enable(0, 0);
    adc_ch = adc_cb.channel;
    adc_cb.channel = BIT(ADCCH_VBAT) | BIT(ADCCH_BGOP);
    p111_en = pll1_disable();//close pll1

    WDT_DIS();
    xo26mcon = XO26MCON;
    XO26MCON &= ~((0X1F)<<0);
    XO26MCON &= ~(0x03 << 28);
    XO26MCON |= BIT(8);
    XO26MCON  &= ~BIT(9);
    printf("rtc_power_test XO26MCON = 0x%X\n",XO26MCON);

    i = 2;
    while(i) {
        static u32 time_old = 0;
        u32 time_cur = RTCCNT;
        if (time_old != time_cur) {
            time_old = time_cur;
//            printf("[%d]", time_cur);
            i--;
        }
        delay_ms(10);
    }
    gie =  PICCON;
    PICCON &= ~BIT(0);
    PICCONCLR = BIT(0);                 //Globle IE disable

    RTCCON |= BIT(8);
    rtc_set_alarm_wakeup(30);////设置多少秒后闹钟唤醒。

    io_ade = GPIOADE;
    io_bde = GPIOBDE;
    io_ede = GPIOEDE;
    io_fde = GPIOFDE;
    io_fpu = GPIOFPU;
    io_fpd = GPIOFPD;
    io_fpd200k = GPIOFPD200K;
    io_fpu200k = GPIOFPU200K;
    io_fpd300 = GPIOFPD300;
    io_fpu300 = GPIOFPU300;
    io_gde = GPIOGDE;

    GPIOADE = 0;
    GPIOBDE = 0;
    GPIOEDE = 0;
    GPIOFDE = 0;
    GPIOFPU = 0;
    GPIOFPD = 0;
    GPIOFPD200K = 0;
    GPIOFPU200K = 0;
    GPIOFPD300 = 0;
    GPIOFPU300 = 0;
    GPIOGDE = BIT(2)| BIT(4);       //SPICS

    usbcon0 = USBCON0;
    clkcon0 = CLKCON0;
    pwrcon0 = PWRCON0;
    pll0con = PLL0CON;
    lpmcon = LPMCON;
    rtccon3 = RTCCON3;
    rtccon4 = RTCCON4;
    rtccon5 = RTCCON5;
    rfpwrcon0 = RFPWRCON0;
    rftxrsv = RFTXRSV ;
    rfrxrsv = RFRXRSV ;
    rfsxrsv = RFSXRSV ;
    rfpllcon0 = RFPLLCON0;
    fmrxangcon0 = FMRXANGCON0;
    fmrxangcon2 = FMRXANGCON2;

    USBCON0 = BIT(5);   //IE disable
    USBCON1 = 0;

    CLKCON0 &=  ~(0x3<<10);    //bt clk
    CLKCON0  &= ~BIT(28);               //select saradc_clk  1: x26m_clkdiv4  //0 rc clk
    CLKCON0 |= BIT(0);                  //enable RC
    asm("nop");asm("nop");asm("nop");
    CLKCON0 = (CLKCON0 & ~(0x3 << 2));  //system clk select RC
    asm("nop");asm("nop");asm("nop");   //

    PLL0CON &= ~BIT(13);                //PLL SDM Dis
    PLL0CON &= ~BIT(6);                 //PLL Analog Dis
    PLL0CON &= ~BIT(12);                //PLL LDO DIS

    //test
    RFPWRCON0 = 0;
    RFTXRSV =0;
    RFRXRSV = 0;
    RFSXRSV = 0;
    RFPLLCON0 = 0;

    RTCCON4 &= ~BIT(15);
    RTCCON5 |= (0x3f<<2);
    RTCCON4 = ((RTCCON4 & ~(0X1F)) | 0xa);
    RTCCON3 &= ~BIT(4);

    FMRXANGCON0 = 0;
    PWRCON0 = (PWRCON0 & ~0xf) | (0x2);            //VCORES3~0  //5  //467
    PWRCON0 = (PWRCON0 & ~(0xF<<4)) | (0x0<<4);    //VIOS3~0   //4   //
    PWRCON0 &= ~BIT(8);   //bat div2 en
    PWRCON0 &= ~BIT(22);   //bat div2 en

    wakeup_disable();
    //WKO WAKE UP
    WKUPEDG |= BIT(5);
    WKUPCPND = 0xff << 16;
    WKUPCON |= BIT(5);

    //假关机, 进入sleep, 等待唤WKO唤醒

    while(1) {
        LPMCON |= BIT(0);
        delay_us(10000);
        if ((RTCCON & BIT(17))) {
            break;
        }
        if (wakeup_get_status()) {
            break;
        }
    }
       //recover

    GPIOADE = io_ade;
    GPIOBDE = io_bde;
    GPIOEDE = io_ede;
    GPIOFDE = io_fde;
    GPIOFPU = io_fpu;
    GPIOFPD = io_fpd;
    GPIOFPD200K = io_fpd200k;
    GPIOFPU200K = io_fpu200k;
    GPIOFPD300 = io_fpd300;
    GPIOFPU300 = io_fpu300;
    GPIOGDE = io_gde;

    wakeup_disable();

    RTCCON3 = rtccon3;
    RTCCON4 = rtccon4;
    RTCCON5 = rtccon5;
    LPMCON = lpmcon;
    RFPWRCON0 = rfpwrcon0;
    RFTXRSV   = rftxrsv  ;
    RFRXRSV   = rfrxrsv  ;
    RFSXRSV   = rfsxrsv  ;
    RFPLLCON0 = rfpllcon0;

    WDT_EN();
    FMRXANGCON0 = fmrxangcon0;
    FMRXANGCON2 = fmrxangcon2;
    XO26MCON = xo26mcon;
    asm("nop");asm("nop");asm("nop");
    PLL0CON = pll0con;
    asm("nop");asm("nop");asm("nop");
    PWRCON0 = pwrcon0;
    asm("nop");asm("nop");asm("nop");
    CLKCON0 = clkcon0;
    asm("nop");asm("nop");asm("nop");
    USBCON0 = usbcon0;
    PICCON |= gie;
    if (p111_en) {
        pll1_enable();
    }

    adc_cb.channel = adc_ch;
    bsp_saradc_init(adc_cb.channel);
    sys_set_tmr_enable(1, 1);
    dac_restart();
    bsp_change_volume(sys_cb.vol);

        printf("END\n");
}
#endif // ALARM_WAKEUP

#endif  //FUNC_CLOCK_EN
